home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / gnu / gnu_oleo_1_2_2.lha / oleo-1.2.2 / decompile.c < prev    next >
C/C++ Source or Header  |  1993-03-03  |  19KB  |  835 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20. #include "sysdef.h"
  21. #include "global.h"
  22. #include "eval.h"
  23. #include "cell.h"
  24. #include "io-utils.h"
  25.  
  26.  
  27.  
  28. struct pr_node
  29.   {
  30.     int tightness;
  31.     int len;
  32.     char string[1];
  33.   };
  34.  
  35.  
  36. static VOIDSTAR save_decomp;
  37. static CELLREF decomp_row;
  38. static CELLREF decomp_col;
  39.  
  40. /* These #defines are so that we don't have to duplicate code below */
  41. /* JF: now obsolete, and should be trashed. */
  42.  
  43. #define F0    a0?"@%s()":"%s()"
  44. #define F1    a0?"@%s(%s)":"%s(%s)"
  45. #define F2    a0?"@%s(%s, %s)":"%s(%s, %s)"
  46. #define F3    a0?"@%s(%s, %s, %s)":"%s(%s, %s, %s)"
  47. #define F4    a0?"@%s(%s, %s, %s, %s)":"%s(%s, %s, %s, %s)"
  48. #define FN1    a0?"@%s(%s":"%s(%s"
  49.  
  50. /* We decompile things with these wierd node-things.  It's ugly, but it works.
  51.  */
  52. #ifdef __STDC__
  53. static struct pr_node *
  54. n_alloc (int size, int tightness, char *fmt,...)
  55. #else
  56. static struct pr_node *
  57. n_alloc (size, tightness, fmt, va_alist)
  58.      int size;
  59.      int tightness;
  60.      char *fmt;
  61.      va_dcl
  62. #endif
  63. {
  64.   struct pr_node *ret;
  65.   va_list args;
  66.  
  67.   ret = ck_malloc (sizeof (struct pr_node) + size + 1);
  68.   ret->len = size;
  69.   ret->tightness = tightness;
  70.   var_start (args, fmt);
  71.   vsprintf (ret->string, fmt, args);
  72.   va_end (args);
  73.   return ret;
  74. }
  75.  
  76. #define n_free(x)    free(x)
  77.  
  78. static struct pr_node *
  79. byte_decompile (expr)
  80.      unsigned char *expr;
  81. {
  82.   unsigned char byte;
  83.   double tmp_flt;
  84.   long tmp_lng;
  85.   char *tmp_str;
  86.   struct var *v;
  87.   unsigned long_skp;
  88.   unsigned char save_val;
  89.   unsigned jumpto;
  90.  
  91.   struct pr_node *new = 0;
  92.   int pri;
  93.   int aso;
  94.   char *chr;
  95.  
  96.   static struct pr_node **the_line;
  97.   static int line_alloc;
  98.  
  99.   static struct pr_node **c_node;
  100.   struct function *f;
  101.  
  102.   if (!the_line)
  103.     {
  104.       the_line = (struct pr_node **) ck_malloc (20 * sizeof (struct pr_node *));
  105.       line_alloc = 20;
  106.       c_node = the_line;
  107.     }
  108.  
  109. #ifdef TEST
  110.   if (!expr)
  111.     panic ("No expression to decompile");
  112. #endif
  113. next_byte:
  114.   byte = *expr++;
  115.   if (byte < USR1)
  116.     f = &the_funs[byte];
  117.   else if (byte < SKIP)
  118.     {
  119.       tmp_lng = *expr++;
  120.       f = &usr_funs[byte - USR1][tmp_lng];
  121.     }
  122.   else
  123.     f = &skip_funs[byte - SKIP];
  124.  
  125.   if (f->fn_argn & X_J)
  126.     jumpto = *expr++;
  127.   else if (f->fn_argn & X_JL)
  128.     {
  129.       jumpto = expr[0] + ((unsigned) (expr[1]) << 8);
  130.       expr += 2;
  131.     }
  132. #ifdef TEST
  133.   else
  134.     jumpto = 0;
  135. #endif
  136.   switch (GET_COMP (f->fn_comptype))
  137.     {
  138.     case C_IF:
  139.       if (expr[jumpto - 2] != SKIP)
  140.     {
  141.       long_skp = 1;
  142.       save_val = expr[jumpto - 3];
  143.       expr[jumpto - 3] = 0;
  144.     }
  145.       else
  146.     {
  147.       long_skp = 0;
  148.       save_val = expr[jumpto - 2];
  149.       expr[jumpto - 2] = 0;
  150.     }
  151.       c_node[0] = byte_decompile (expr);
  152.       c_node++;
  153.  
  154.       if (long_skp)
  155.     {
  156.       expr[jumpto - 3] = save_val;
  157.       expr += jumpto;
  158.       jumpto = expr[-2] + ((unsigned) (expr[-1]) << 8);
  159.     }
  160.       else
  161.     {
  162.       expr[jumpto - 2] = save_val;
  163.       expr += jumpto;
  164.       jumpto = expr[-1];
  165.     }
  166.       save_val = expr[jumpto];
  167.       expr[jumpto] = 0;
  168.       c_node[0] = byte_decompile (expr);
  169.       c_node -= 2;
  170.       expr[jumpto] = save_val;
  171.       expr += jumpto;
  172.       if (byte == IF || byte == IF_L)
  173.     {
  174.       if (c_node[0]->tightness <= 1)
  175.         new = n_alloc (8 + c_node[0]->len + c_node[1]->len + c_node[2]->len,
  176.                1,
  177.                "(%s) ? %s : %s", c_node[0]->string, c_node[1]->string, c_node[2]->string);
  178.       else
  179.         new = n_alloc (6 + c_node[0]->len + c_node[1]->len + c_node[2]->len,
  180.                1,
  181.                "%s ? %s : %s", c_node[0]->string, c_node[1]->string, c_node[2]->string);
  182.     }
  183.       else
  184.     new = n_alloc (6 + c_node[0]->len + c_node[1]->len + c_node[2]->len + strlen (f->fn_str),
  185.                1000,
  186.                F3, f->fn_str, c_node[0]->string, c_node[1]->string, c_node[2]->string);
  187.       n_free (c_node[0]);
  188.       n_free (c_node[1]);
  189.       n_free (c_node[2]);
  190.       break;
  191.  
  192.     case C_ANDOR:
  193.       save_val = expr[jumpto];
  194.       expr[jumpto] = 0;
  195.       c_node[0] = byte_decompile (expr);
  196.       expr[jumpto] = save_val;
  197.       expr += jumpto;
  198.       c_node++;
  199.       if (ISINFIX (f->fn_comptype))
  200.     {
  201.       pri = GET_IN (f->fn_comptype);
  202.       aso = GET_ASO (f->fn_comptype);
  203.       chr = f->fn_str;
  204.       goto do_infix;
  205.     }
  206.       else
  207.     goto do_fn2;
  208.  
  209.     case C_STR:
  210.       tmp_str = backslash_a_string ((char *) expr + jumpto, 1);
  211.       new = n_alloc (strlen (tmp_str) + 1,
  212.              1000,
  213.              tmp_str);
  214.       break;
  215.  
  216.     case C_CELL:
  217.       {
  218.     int num1, num2;
  219.     char *str;
  220.     CELLREF row, col;
  221.  
  222.     row = GET_ROW (expr);
  223.     col = GET_COL (expr);
  224.     expr += EXP_ADD;
  225.  
  226.     if (a0)
  227.       {
  228.         new = n_alloc (30, 1000, f->fn_str, col_to_str (col), row);
  229.       }
  230.     else
  231.       {
  232.         if (byte & ROWREL)
  233.           {
  234.         num1 = row - decomp_row;
  235.         if (byte & COLREL)
  236.           {
  237.             num2 = col - decomp_col;
  238.             if (row == decomp_row && col == decomp_col)
  239.               str = "rc";
  240.             else if (row == decomp_row)
  241.               {
  242.             str = "rc[%+d]";
  243.             num1 = num2;
  244.               }
  245.             else if (col == decomp_col)
  246.               str = "r[%+d]c";
  247.             else
  248.               str = "r[%+d]c[%+d]";
  249.           }
  250.         else if (row == decomp_row)
  251.           {
  252.             str = "rc%u";
  253.             num1 = num2 = col;
  254.           }
  255.         else
  256.           {
  257.             str = "r[%+d]c%u";
  258.             num2 = col;
  259.           }
  260.           }
  261.         else if (byte & COLREL)
  262.           {
  263.         num1 = row;
  264.         num2 = col - decomp_col;
  265.         if (col == decomp_col)
  266.           str = "r%uc";
  267.         else
  268.           str = "r%uc[%+d]";
  269.           }
  270.         else
  271.           {
  272.         str = "r%uc%u";
  273.         num1 = row;
  274.         num2 = col;
  275.           }
  276.         new = n_alloc (30, 1000, str, num1, num2);
  277.       }
  278.     new->len = strlen (new->string);
  279.       }
  280.       break;
  281.  
  282.     case C_RANGE:
  283.       {
  284.     char tmprbuf[40];
  285.     char tmpcbuf[40];
  286.     struct rng rng;
  287.  
  288.     GET_RNG (expr, &rng);
  289.     expr += EXP_ADD_RNG;
  290.  
  291.     if (a0)
  292.       new = n_alloc (40, 1000, f->fn_str, col_to_str (rng.lc), rng.lr, col_to_str (rng.hc), rng.hr);
  293.     else
  294.       {
  295.         /* Check for special cases */
  296.         if (rng.lr == rng.hr && ((byte & LRREL) ? 1 : 0) == ((byte & HRREL) ? 1 : 0))
  297.           {
  298.         if (byte & LRREL)
  299.           {
  300.             if (rng.lr == decomp_row)
  301.               {
  302.             tmprbuf[0] = 'r';
  303.             tmprbuf[1] = '\0';
  304.               }
  305.             else
  306.               (void) sprintf (tmprbuf, "r[%+d]", rng.lr - decomp_row);
  307.           }
  308.         else
  309.           sprintf (tmprbuf, "r%u", rng.lr);
  310.           }
  311.         else if ((byte & LRREL) && (byte & HRREL))
  312.           {
  313.         int r1, r2, rtmp;
  314.  
  315.         r1 = rng.lr - decomp_row;
  316.         r2 = rng.hr - decomp_row;
  317.         if (r1 < r2)
  318.           rtmp = r1, r1 = r2, r2 = rtmp;
  319.         (void) sprintf (tmprbuf, "r[%+d:%+d]", r1, r2);
  320.           }
  321.         else if ((byte & LRREL))
  322.           (void) sprintf (tmprbuf, "r[%+d]:%u", rng.lr - decomp_row, rng.hr);
  323.         else if (byte & HRREL)
  324.           (void) sprintf (tmprbuf, "r%u:[%+d]", rng.lr, rng.hr - decomp_row);
  325.         else if (rng.lr < rng.hr)
  326.           (void) sprintf (tmprbuf, "r%u:%u", rng.lr, rng.hr);
  327.         else
  328.           (void) sprintf (tmprbuf, "r%u:%u", rng.hr, rng.lr);
  329.  
  330.         if (rng.lc == rng.hc && ((byte & LCREL) ? 1 : 0) == ((byte & HCREL) ? 1 : 0))
  331.           {
  332.         if (byte & LCREL)
  333.           {
  334.             if (rng.lc == decomp_col)
  335.               {
  336.             tmpcbuf[0] = 'c';
  337.             tmpcbuf[1] = '\0';
  338.               }
  339.             else
  340.               sprintf (tmpcbuf, "c[%+d]", rng.lc - decomp_col);
  341.           }
  342.         else
  343.           sprintf (tmpcbuf, "c%u", rng.lc);
  344.           }
  345.         else if ((byte & LCREL) && (byte & HCREL))
  346.           {
  347.         int c1, c2, ctmp;
  348.  
  349.         c1 = rng.lc - decomp_col;
  350.         c2 = rng.hc - decomp_col;
  351.         if (c1 < c2)
  352.           ctmp = c1, c1 = c2, c2 = ctmp;
  353.         (void) sprintf (tmpcbuf, "c[%+d:%+d]", c1, c2);
  354.           }
  355.         else if ((byte & LCREL))
  356.           (void) sprintf (tmpcbuf, "c[%+d]:%u", rng.lc - decomp_col, rng.hc);
  357.         else if (byte & HCREL)
  358.           (void) sprintf (tmpcbuf, "c%u:[%+d]", rng.lc, rng.hc - decomp_col);
  359.         else if (rng.lc < rng.hc)
  360.           (void) sprintf (tmpcbuf, "c%u:%u", rng.lc, rng.hc);
  361.         else
  362.           (void) sprintf (tmpcbuf, "c%u:%u", rng.hc, rng.lc);
  363.  
  364.         new = n_alloc (40, 1000, "%s%s", tmprbuf, tmpcbuf);
  365.       }
  366.     new->len = strlen (new->string);
  367.       }
  368.       break;
  369.  
  370.     case C_CONST:
  371.       new = n_alloc (strlen (f->fn_str) + 1, 1000, f->fn_str);
  372.       break;
  373.  
  374.     case C_FN0:
  375.     case C_FN0X:
  376.     case C_FN0 | C_T:
  377.       new = n_alloc (strlen (f->fn_str) + 3,
  378.              1000,
  379.              F0,
  380.              f->fn_str);
  381.       break;
  382.  
  383.     case C_FN1:
  384.       --c_node;
  385.       new = n_alloc (c_node[0]->len + strlen (f->fn_str) + 3,
  386.              1000,
  387.              F1, f->fn_str, c_node[0]->string);
  388.       n_free (*c_node);
  389.       break;
  390.  
  391.     case C_UNA:
  392.       --c_node;
  393.       if (c_node[0]->tightness < 9)
  394.     {
  395.       new = n_alloc (3 + c_node[0]->len,
  396.              9,
  397.              "%s(%s)", f->fn_str, c_node[0]->string);
  398.     }
  399.       else
  400.     {
  401.       new = n_alloc (1 + c_node[0]->len,
  402.              9,
  403.              "%s%s", f->fn_str, c_node[0]->string);
  404.     }
  405.       n_free (*c_node);
  406.       break;
  407.  
  408.     case C_INF:
  409.       pri = GET_IN (f->fn_comptype);
  410.       aso = GET_ASO (f->fn_comptype);
  411.       chr = f->fn_str;
  412.  
  413.     do_infix:
  414.       c_node -= 2;
  415.       if (c_node[0]->tightness < pri || (c_node[0]->tightness == pri && aso != 1))
  416.     {
  417.       if (c_node[1]->tightness < pri || (c_node[1]->tightness == pri && aso != -1))
  418.         new = n_alloc (7 + c_node[0]->len + c_node[1]->len,
  419.                pri,
  420.          "(%s) %s (%s)", c_node[0]->string, chr, c_node[1]->string);
  421.       else
  422.         new = n_alloc (5 + c_node[0]->len + c_node[1]->len,
  423.                pri,
  424.            "(%s) %s %s", c_node[0]->string, chr, c_node[1]->string);
  425.     }
  426.       else if (c_node[1]->tightness < pri || (c_node[1]->tightness == pri && aso != -1))
  427.     new = n_alloc (5 + c_node[0]->len + c_node[1]->len,
  428.                pri,
  429.            "%s %s (%s)", c_node[0]->string, chr, c_node[1]->string);
  430.       else
  431.     new = n_alloc (3 + c_node[0]->len + c_node[1]->len,
  432.                pri,
  433.              "%s %s %s", c_node[0]->string, chr, c_node[1]->string);
  434.  
  435.       n_free (c_node[0]);
  436.       n_free (c_node[1]);
  437.       break;
  438.  
  439.     case C_FN2:
  440.     do_fn2:
  441.       c_node -= 2;
  442.       new = n_alloc (c_node[0]->len + c_node[1]->len + strlen (f->fn_str) + 5,
  443.              1000,
  444.              F2, f->fn_str, c_node[0]->string, c_node[1]->string);
  445.       n_free (c_node[0]);
  446.       n_free (c_node[1]);
  447.       break;
  448.  
  449.     case C_FN3:
  450.       c_node -= 3;
  451.       new = n_alloc (c_node[0]->len + c_node[1]->len + c_node[2]->len + strlen (f->fn_str) + 7,
  452.              1000,
  453.              F3,
  454.              f->fn_str,
  455.              c_node[0]->string,
  456.              c_node[1]->string,
  457.              c_node[2]->string);
  458.       n_free (c_node[0]);
  459.       n_free (c_node[1]);
  460.       n_free (c_node[2]);
  461.       break;
  462.  
  463.     case C_FNN:
  464.       aso = *expr++;
  465.       c_node -= aso;
  466.  
  467.       if (aso == 1)
  468.     new = n_alloc (3 + c_node[0]->len + strlen (f->fn_str),
  469.                1000,
  470.                F1, f->fn_str, c_node[0]->string);
  471.       else
  472.     {
  473.       new = n_alloc (2 + c_node[0]->len + strlen (f->fn_str),
  474.              1000,
  475.              FN1, f->fn_str, c_node[0]->string);
  476.       --aso;
  477.       for (pri = 1; pri < aso; pri++)
  478.         {
  479.           n_free (c_node[0]);
  480.           c_node[0] = new;
  481.           new = n_alloc (2 + new->len + c_node[pri]->len,
  482.                  1000,
  483.                  "%s, %s", new->string, c_node[pri]->string);
  484.         }
  485.       n_free (c_node[0]);
  486.       c_node[0] = new;
  487.       new = n_alloc (3 + new->len + c_node[aso]->len,
  488.              1000,
  489.              "%s, %s)", new->string, c_node[aso]->string);
  490.     }
  491.       n_free (c_node[0]);
  492.       break;
  493.  
  494.     case C_FN4:
  495.       c_node -= 4;
  496.       new = n_alloc (c_node[0]->len + c_node[1]->len + c_node[2]->len + c_node[3]->len + strlen (f->fn_str) + 6,
  497.              1000,
  498.              F4,
  499.              f->fn_str,
  500.              c_node[0]->string,
  501.              c_node[1]->string,
  502.              c_node[2]->string,
  503.              c_node[3]->string);
  504.       n_free (c_node[0]);
  505.       n_free (c_node[1]);
  506.       n_free (c_node[2]);
  507.       n_free (c_node[3]);
  508.       break;
  509.  
  510.     case C_ERR:
  511.       tmp_str = (char *) expr + jumpto;
  512.       expr++;
  513.       new = n_alloc (strlen (tmp_str) + 1, 1000, tmp_str);
  514.       /* bcopy((VOIDSTAR)expr,(VOIDSTAR)&tmp_str,sizeof(char *));
  515.         expr+=sizeof(char *);
  516.         new=n_alloc(strlen(tmp_str)+1,1000,f->fn_str,tmp_str); */
  517.       break;
  518.  
  519.     case C_FLT:
  520.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_flt, sizeof (double));
  521.       expr += sizeof (double);
  522.       new = n_alloc (20, 1000, f->fn_str, tmp_flt);
  523.       new->len = strlen (new->string);
  524.       break;
  525.  
  526.     case C_INT:
  527.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_lng, sizeof (long));
  528.       expr += sizeof (long);
  529.       new = n_alloc (20, 1000, f->fn_str, tmp_lng);
  530.       new->len = strlen (new->string);
  531.       break;
  532.  
  533.     case C_VAR:
  534.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & v, sizeof (struct var *));
  535.       expr += sizeof (struct var *);
  536.       new = n_alloc (strlen (v->var_name) + 1,
  537.              1000,
  538.              f->fn_str, v->var_name);
  539.       break;
  540.  
  541.  
  542.     default:
  543.       panic ("Bad decompile %d", f->fn_comptype);
  544.     }
  545.   *c_node++ = new;
  546.   if (c_node == &the_line[line_alloc])
  547.     {
  548.       line_alloc *= 2;
  549.       the_line = ck_realloc (the_line, line_alloc * sizeof (struct pr_node *));
  550.       c_node = &the_line[line_alloc / 2];
  551.     }
  552.  
  553.   if (*expr)
  554.     goto next_byte;
  555.  
  556.   /* if(c_node != &the_line[1]) {
  557.         io_error_msg("%d values on decompile stack!",c_node - the_line);
  558.         return the_line[0];
  559.     } */
  560.   new = *--c_node;
  561.   /* free(the_line); */
  562.   return new;
  563. }
  564.  
  565. /* Actual entry points to this file */
  566. /* decomp(row, col, cell) returns a string that can be byte_compiled to create
  567.    cell->formula  decomp_free() frees up the allocated string */
  568. #if __STDC__
  569. char *
  570. decomp (CELLREF r, CELLREF c, CELL *cell)
  571. #else
  572. char *
  573. decomp (r, c, cell)
  574.      CELLREF r;
  575.      CELLREF c;
  576.      CELL *cell;
  577. #endif
  578. {
  579.   struct pr_node *ret;
  580.   char *str;
  581.   extern char *bname[];
  582.  
  583.   decomp_row = r;
  584.   decomp_col = c;
  585.   if (cell->cell_formula == 0)
  586.     {
  587.       switch (GET_TYP (cell))
  588.     {
  589.     case 0:
  590.       str = ck_malloc (1);
  591.       str[0] = '\0';
  592.       break;
  593.     case TYP_FLT:
  594.       str = strdup (flt_to_str (cell->cell_flt));
  595.       break;
  596.     case TYP_INT:
  597.       str = ck_malloc (20);
  598.       sprintf (str, "%ld", cell->cell_int);
  599.       break;
  600.     case TYP_STR:
  601.       str = strdup (backslash_a_string (cell->cell_str, 1));
  602.       break;
  603.     case TYP_BOL:
  604.       str = strdup (bname[cell->cell_bol]);
  605.       break;
  606.     case TYP_ERR:
  607.       str = strdup (ename[cell->cell_bol]);
  608.       break;
  609. #ifdef TEST
  610.     default:
  611.       str = 0;
  612.       panic ("Unknown type %d in decomp", GET_TYP (cell));
  613. #endif
  614.     }
  615.       save_decomp = (VOIDSTAR) str;
  616.       return str;
  617.     }
  618.   else
  619.     ret = byte_decompile (cell->cell_formula);
  620.   save_decomp = (VOIDSTAR) ret;
  621.   return &(ret->string[0]);
  622. }
  623.  
  624. void
  625. decomp_free ()
  626. {
  627. #ifdef TEST
  628.   if (!save_decomp)
  629.     panic ("No save decomp");
  630.   n_free (save_decomp);
  631.   save_decomp = (VOIDSTAR) 0;
  632. #else
  633.   n_free (save_decomp);
  634. #endif
  635. }
  636.  
  637. /* This takes a string and returns a backslashed form suitable for printing.
  638.    Iff add_quote is true, it'll add "s at the beginning and end.
  639.    Note that this returns a pointer to a static area that is overwritten with
  640.    each call. . .
  641.  */
  642. char *
  643. backslash_a_string (string, add_quote)
  644.      char *string;
  645.      int add_quote;
  646. {
  647.   char *pf;
  648.   char *pt;
  649.   int ch;
  650.   int size;
  651.   int len;
  652.  
  653.   static char *cbuf;
  654.   static int s_cbuf;
  655.  
  656. #define ALLOC_PT()                \
  657.     len=strlen(pf);                \
  658.     size=pf-string;                \
  659.     if(s_cbuf<3+size+4*len) {        \
  660.         s_cbuf=3+size+4*len;        \
  661.         cbuf= (cbuf) ? ck_realloc(cbuf,s_cbuf) : ck_malloc(s_cbuf); \
  662.     }                    \
  663.     if(size)                \
  664.         bcopy(string,cbuf,size);    \
  665.     pt=cbuf+size;                \
  666.  
  667.  
  668.   pt = 0;
  669.   pf = string;
  670.   if (add_quote)
  671.     {
  672.       ALLOC_PT ()
  673.     * pt++ = '"';
  674.     }
  675.   for (; *pf; pf++)
  676.     {
  677.       ch = *pf;
  678.       if (ch >= ' ' && ch <= '~' && ch != '\\' && (ch != '"' || !add_quote))
  679.     {
  680.       if (pt)
  681.         *pt++ = ch;
  682.       continue;
  683.     }
  684.  
  685.       if (!pt)
  686.     {
  687.       ALLOC_PT ()
  688.     }
  689.       if (ch == '\\')
  690.     {
  691.       *pt++ = '\\';
  692.       *pt++ = '\\';
  693.     }
  694.       else if (ch == '"')
  695.     {
  696.       *pt++ = '\\';
  697.       *pt++ = ch;
  698.     }
  699.       else
  700.     {
  701.       *pt++ = '\\';
  702.       *pt++ = ((ch >> 6) & 0x3) + '0';
  703.       *pt++ = ((ch >> 3) & 0x7) + '0';
  704.       *pt++ = (ch & 0x7) + '0';
  705.     }
  706.     }
  707.   if (add_quote)
  708.     *pt++ = '"';
  709.   if (pt)
  710.     {
  711.       *pt++ = '\0';
  712.       return cbuf;
  713.     }
  714.   return string;
  715. }
  716.  
  717. #ifdef TEST
  718. void
  719. dbg_print_formula (expr)
  720.      unsigned char *expr;
  721. {
  722.   unsigned char byte;
  723.   struct function *f;
  724.   double tmp_flt;
  725.   char *tmp_str;
  726.   long tmp_int;
  727.   struct var *v;
  728.   struct rng rng;
  729.   char *buf;
  730.   unsigned jumpto;
  731.   extern char print_buf[];
  732.   extern char *strcpy ();
  733.  
  734.   if (!expr)
  735.     return;
  736.   strcpy (print_buf, "Formula: ");
  737.   buf = print_buf + 9;
  738.   while (*expr)
  739.     {
  740.       byte = *expr++;
  741.  
  742.       if (byte < USR1)
  743.     f = &the_funs[byte];
  744.       else if (byte < SKIP)
  745.     {
  746.       tmp_int = *expr++;
  747.       f = &usr_funs[byte - USR1][tmp_int];
  748.     }
  749.       else
  750.     f = &skip_funs[byte - SKIP];
  751.  
  752.       if (f->fn_argn & X_J)
  753.     jumpto = *expr++;
  754.       else if (f->fn_argn & X_JL)
  755.     {
  756.       jumpto = expr[0] + ((unsigned) (expr[1]) << 8);
  757.       expr += 2;
  758.     }
  759.       else
  760.     jumpto = 0;
  761.  
  762.       switch (GET_COMP (f->fn_comptype))
  763.     {
  764.     case C_IF:
  765.       sprintf (buf, " if%d.%u", byte, jumpto);
  766.       break;
  767.     case C_ANDOR:
  768.       sprintf (buf, " andor%d.%u", byte, jumpto);
  769.       break;
  770.     case C_ERR:
  771.       tmp_str = (char *) (expr + jumpto);
  772.       byte = *expr++;
  773.       sprintf (buf, " err%d.%p(%s)", byte, tmp_str, tmp_str);
  774.       break;
  775.     case C_FLT:
  776.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_flt, sizeof (double));
  777.       expr += sizeof (double);
  778.       sprintf (buf, " flt.%.15g", tmp_flt);
  779.       break;
  780.     case C_INT:
  781.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & tmp_int, sizeof (long));
  782.       expr += sizeof (long);
  783.       sprintf (buf, " int.%ld", tmp_int);
  784.       break;
  785.     case C_STR:
  786.       tmp_str = (char *) (expr + jumpto);
  787.       sprintf (buf, " str.%p.%s", tmp_str, tmp_str);
  788.       break;
  789.     case C_VAR:
  790.       bcopy ((VOIDSTAR) expr, (VOIDSTAR) & v, sizeof (struct var *));
  791.       expr += sizeof (struct var *);
  792.       sprintf (buf, " var.%p.%s", v, v->var_name);
  793.       break;
  794.     case C_CELL:
  795.       sprintf (buf, " ref%d.%u.%u", byte, GET_ROW (expr), GET_COL (expr));
  796.       expr += EXP_ADD;
  797.       break;
  798.     case C_RANGE:
  799.       GET_RNG (expr, &rng);
  800.       sprintf (buf, " rng%d.%u-%u,%u-%u", byte, rng.lr, rng.hr, rng.lc, rng.hc);
  801.       expr += EXP_ADD_RNG;
  802.       break;
  803.     case C_FN0:
  804.     case C_FN0X:
  805.     case C_FN1:
  806.     case C_FN2:
  807.     case C_FN3:
  808.     case C_FN4:
  809.     case C_UNA:
  810.     case C_INF:
  811.       sprintf (buf, " fun%d.%s.%p", byte, f->fn_str, f->fn_fun);
  812.       break;
  813.  
  814.     case C_FNN:
  815.       sprintf (buf, " funn%d.%s.%p.%d", byte, f->fn_str, f->fn_fun, *expr++);
  816.       break;
  817.     case C_CONST:
  818.       sprintf (buf, " const%s", f->fn_str);
  819.       break;
  820.     case C_SKIP:
  821.       sprintf (buf, " skip.%d", jumpto);
  822.       break;
  823.     case 0:
  824.       sprintf (buf, " ???%d", byte);
  825.       break;
  826.     default:
  827.       io_error_msg ("Unknown decompile type %d", f->fn_comptype);
  828.     }
  829.       buf += strlen (buf);
  830.     }
  831.   io_text_line (print_buf);
  832. }
  833.  
  834. #endif
  835.